#include "ASMInstruction.hpp"
#include "CodeGen.hpp"
#include "Module.hpp"

#include <iostream>
#include <memory>
#include <unordered_map>

// 声明全局变量和主函数翻译函数
void declare_global(CodeGen *codegen);
void translate_main(CodeGen *codegen);

int main() {
    // 初始化编译器模块和代码生成器
    auto *module = new Module();
    auto *codegen = new CodeGen(module);

    // 指定后续生成的汇编代码属于.text段（代码段）
    codegen->append_inst(".text", ASMInstruction::Atrribute);

    // 声明全局变量并生成主函数代码
    declare_global(codegen);
    codegen->append_inst(".text", ASMInstruction::Atrribute); // 确保回到代码段
    translate_main(codegen);

    // 输出生成的汇编代码
    std::cout << codegen->print();
    
    // 清理资源
    delete codegen;
    delete module;
    return 0;
}

// 全局变量声明实现
void declare_global(CodeGen *codegen) {
    /* ============== 数据段声明 ============== */
    codegen->append_inst(".data", ASMInstruction::Atrribute);  // 切换到数据段
    codegen->append_inst(".globl a", ASMInstruction::Atrribute); // 全局可见符号
    codegen->append_inst(".type a, @object", ASMInstruction::Atrribute); // 变量类型
    codegen->append_inst(".size a, 4", ASMInstruction::Atrribute); // 4字节大小
    codegen->append_inst("a", ASMInstruction::Label);  // 变量标签
    codegen->append_inst(".zero 4");  // 初始化为0的4字节空间
}

// 主函数实现：全局变量访问示例
void translate_main(CodeGen *codegen) {
    // 符号表：记录局部变量在栈帧中的偏移位置
    std::unordered_map<std::string, int> offset_map;

    /* ============== 函数声明部分 ============== */
    codegen->append_inst(".globl main", ASMInstruction::Atrribute);  // 全局可见
    codegen->append_inst(".type main, @function", ASMInstruction::Atrribute); // 函数类型

    /* ============== 函数入口点 ============== */
    codegen->append_inst("main", ASMInstruction::Label);  // 函数入口标签

    /* ============== 序言部分 (Prologue) ============== */
    // 分配32字节栈空间（包含保存寄存器和局部变量的空间）
    codegen->append_inst("addi sp, sp, -32");
    // 保存返回地址寄存器(ra)
    codegen->append_inst("sd ra, 24(sp)");
    // 保存旧的帧指针(s0)
    codegen->append_inst("sd s0, 16(sp)");
    // 设置新的帧指针(s0 = sp + 32)
    codegen->append_inst("addi s0, sp, 32");

    /* ============== 代码主体部分 ============== */
    codegen->append_inst(".main_label_entry", ASMInstruction::Label);  // 主代码段标签

    /* 全局变量写入操作 */
    codegen->append_inst("li t0, 10");           // 加载立即数10到t0
    codegen->append_inst("la t1, a");            // 获取全局变量a的地址
    codegen->append_inst("sw t0, 0(t1)");        // 将10存储到a的地址

    /* 全局变量读取操作 */
    offset_map["%op0"] = -24;  // 局部变量存储在s0-24位置
    codegen->append_inst("la t0, a");            // 再次获取a的地址
    codegen->append_inst("lw t1, 0(t0)");        // 从a的地址加载值
    codegen->append_inst("sw t1, -24(s0)");      // 存储到局部变量%op0

    /* ============== 函数返回部分 ============== */
    codegen->append_inst("lw a0, -24(s0)");      // 加载返回值到a0寄存器
    codegen->append_inst("j .main_exit");        // 跳转到公共退出点

    /* ============== 收尾部分 (Epilogue) ============== */
    codegen->append_inst(".main_exit", ASMInstruction::Label);
    codegen->append_inst("ld ra, 24(sp)");       // 恢复返回地址
    codegen->append_inst("ld s0, 16(sp)");       // 恢复帧指针
    codegen->append_inst("addi sp, sp, 32");     // 释放栈空间
    codegen->append_inst("jr ra");               // 函数返回
}
